 /* Name       : Sample Comm's Program - 1024 Byte Buffer - buff1024.c   */
 /* Written By : Craig Peacock <cpeacock@senet.com.au>                   */

 /*       Copyright 1997 CRAIG PEACOCK <cpeacock@senet.com.au>           */

 /*         See http://www.senet.com.au/~cpeacock/serial1.htm            */
 /*                       For More Information                           */



#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <curses.h>

#include "params.h"
#include "fake_int.h"
#include "disk_controller_constants.h"
typedef unsigned char uchar;	       

uint* dma;

#define PORT BASE_ADDRESS

uchar inportb(unsigned int port)
{
	unsigned int result;
    __asm__ 
    (
		"movl  %[port],%%eax\n"
		"movw  %%ax,%%dx\n"
        "inb  %%dx,%%al\n"
        "movl %%eax,%[result]\n"
    :
		[result]"=r" (result)
	:
		[port] "r" (port)
	:"eax");	
	return (uchar)result;
}

void outportb(unsigned int port, uchar value)
{
    __asm__ 
    (
		"movl  %[port],%%eax\n"
		"movw  %%ax,%%dx\n"
		"movl  %[value],%%eax\n"
        "outb %%al,%%dx\n"
    :
	:
		[port] "r" (port),
		[value] "r" ((unsigned int)value)
	:"eax","edx");	
}

void write_reg(uchar reg, uchar data)
{
    outportb(PORT+0, reg);
    outportb(PORT+1, data);
}

uchar read_reg(uchar reg)
{
    outportb(PORT+0, reg);
    return inportb(PORT+1);
}

void set_address(uchar head, uchar sector, uchar cylinder_high, uchar cylinder_low)
{
     write_reg(HEAD, head);
     write_reg(SECTOR, sector);
     write_reg(CYLINDER_HIGH, cylinder_high);
     write_reg(CYLINDER_LOW, cylinder_low);
}

void read_sector(uchar head, uchar sector, uchar cylinder_high, uchar cylinder_low)
{
    set_address(head, sector, cylinder_high, cylinder_low);
    write_reg(DISK_OP, OP_READ_DATA);
    
    uchar data_check[4];
    data_check[0] = head;
    data_check[1] = sector;
    data_check[2] = cylinder_high;
    data_check[3] = cylinder_low;
    for(uint i=0;i<SECTOR_SIZE/sizeof(uint);i++)
    {
        if (dma[i] != *((int*)data_check) + i)
        {
            printf("Error on %02x termintating\n", *((int*)data_check));
            throw -1;
        }
    }
    
}

void write_sector(uchar head, uchar sector, uchar cylinder_high, uchar cylinder_low)
{
    uchar data_check[4];
    data_check[0] = head;
    data_check[1] = sector;
    data_check[2] = cylinder_high;
    data_check[3] = cylinder_low;
    for(uint i=0;i<SECTOR_SIZE/sizeof(uint);i++)
        dma[i] = *((int*)data_check) + i;

    set_address(head, sector, cylinder_high, cylinder_low);
    write_reg(DISK_OP, OP_WRITE_DATA);
}

int main(int argc, char** argv){
 printf("COMMAND: ");
 for(uint i=0;i<argc;i++)
    printf("%s ", argv[i]);
 printf("\n");
 dma = (uint*)init_dma();
 uchar sectorsPerTrack = read_reg(SECTORS_PER_TRACK);
 printf("Sectors per track %d \n", sectorsPerTrack);
 

 for(uint h=0;h<HEAD_COUNT;h++)
    for(uint c_h=0;c_h<CYLINDER_HI_COUNT;c_h++)
        for(uint c_l=0;c_l<0x100;c_l++)
            for(uint s=0;s<SECTOR_PER_TRACK;s++)
            {
                write_sector(h, s, c_h, c_l);
            }

 for(uint h=0;h<HEAD_COUNT;h++)
    for(uint c_h=0;c_h<CYLINDER_HI_COUNT;c_h++)
        for(uint c_l=0;c_l<0x100;c_l++)
            for(uint s=0;s<SECTOR_PER_TRACK;s++)
            {
                read_sector(h, s, c_h, c_l);
            } 

 printf("all ok\n");
 
 clean_dma();
 return 0;
}

